<template>
  <div class="upload-field">
    <el-upload
      v-model:file-list="fileList"
      :action="uploadAction"
      :headers="headers"
      :before-upload="beforeUpload"
      :on-success="onSuccess"
      :on-error="onError"
      :on-exceed="onExceed"
      :limit="limit"
      :accept="accept"
      :multiple="multiple"
      :auto-upload="autoUpload"
      :drag="drag"
      :list-type="listType"
    >
      <template #trigger>
        <slot name="trigger">
          <el-button type="primary">选择文件</el-button>
        </slot>
      </template>

      <template #tip>
        <slot name="tip">
          <div class="el-upload__tip" v-if="tip">
            {{ tip }}
          </div>
        </slot>
      </template>

      <!-- 拖拽上传提示 -->
      <template v-if="drag" #default>
        <el-icon class="el-icon--upload">
          <upload-filled />
        </el-icon>
        <div class="el-upload__text">
          将文件拖到此处，或<em>点击上传</em>
        </div>
      </template>
    </el-upload>

    <!-- 预览区域 -->
    <div v-if="preview && fileList.length > 0" class="preview-area">
      <template v-if="listType === 'picture-card'">
        <el-image
          v-for="file in fileList"
          :key="file.uid"
          :src="file.url"
          :preview-src-list="previewUrls"
          fit="cover"
        />
      </template>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import type { UploadProps, UploadUserFile } from 'element-plus'

const props = withDefaults(defineProps<{
  modelValue?: string | string[]
  action?: string
  headers?: Record<string, string>
  accept?: string
  limit?: number
  multiple?: boolean
  autoUpload?: boolean
  drag?: boolean
  preview?: boolean
  listType?: 'text' | 'picture' | 'picture-card'
  tip?: string
}>(), {
  action: '/api/upload',
  headers: () => ({}),
  accept: '*/*',
  limit: 1,
  multiple: false,
  autoUpload: true,
  drag: false,
  preview: true,
  listType: 'text'
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: string | string[]): void
  (e: 'success', response: any, file: UploadUserFile): void
  (e: 'error', error: Error, file: UploadUserFile): void
}>()

// 文件列表
const fileList = ref<UploadUserFile[]>([])

// 上传地址
const uploadAction = computed(() => props.action)

// 预览URL列表
const previewUrls = computed(() => fileList.value.map(file => file.url))

// 上传前处理
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  // 这里可以添加文件验证逻辑
  return true
}

// 上传成功回调
const onSuccess: UploadProps['onSuccess'] = (response, file) => {
  const uploadFile = file as UploadUserFile
  if (props.multiple) {
    emit('update:modelValue', fileList.value.map(f => f.url))
  } else {
    emit('update:modelValue', uploadFile.url)
  }
  emit('success', response, uploadFile)
}

// 上传失败回调
const onError: UploadProps['onError'] = (error, file) => {
  emit('error', error, file as UploadUserFile)
}

// 超出限制回调
const onExceed: UploadProps['onExceed'] = (files) => {
  console.warn(`超出上传数量限制: ${props.limit}`)
}
</script>

<style scoped lang="scss">
.upload-field {
  .preview-area {
    margin-top: 16px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 8px;

    .el-image {
      width: 100%;
      height: 100px;
      border-radius: 4px;
      overflow: hidden;
    }
  }
}
</style> 